//===----------------------------------------------------------------------===//
//
// This source file is part of the Soto for AWS open source project
//
// Copyright (c) 2017-2024 the Soto project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of Soto project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

// THIS FILE IS AUTOMATICALLY GENERATED by https://github.com/soto-project/soto-codegenerator.
// DO NOT EDIT.

#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
@_exported import SotoCore

/// Service object for interacting with AWS SavingsPlans service.
///
/// Savings Plans are a pricing model that offer significant savings on Amazon Web Services usage (for example, on Amazon EC2 instances). You commit to a consistent amount of usage per hour, in the specified currency, for a term of one or three years, and receive a lower price for that usage. For more information, see the Amazon Web Services Savings Plans User Guide.
public struct SavingsPlans: AWSService {
    // MARK: Member variables

    /// Client used for communication with AWS
    public let client: AWSClient
    /// Service configuration
    public let config: AWSServiceConfig

    // MARK: Initialization

    /// Initialize the SavingsPlans client
    /// - parameters:
    ///     - client: AWSClient used to process requests
    ///     - region: Region of server you want to communicate with. This will override the partition parameter.
    ///     - partition: AWS partition where service resides, standard (.aws), china (.awscn), government (.awsusgov).
    ///     - endpoint: Custom endpoint URL to use instead of standard AWS servers
    ///     - middleware: Middleware chain used to edit requests before they are sent and responses before they are decoded 
    ///     - timeout: Timeout value for HTTP requests
    ///     - byteBufferAllocator: Allocator for ByteBuffers
    ///     - options: Service options
    public init(
        client: AWSClient,
        region: SotoCore.Region? = nil,
        partition: AWSPartition = .aws,
        endpoint: String? = nil,
        middleware: AWSMiddlewareProtocol? = nil,
        timeout: TimeAmount? = nil,
        byteBufferAllocator: ByteBufferAllocator = ByteBufferAllocator(),
        options: AWSServiceConfig.Options = []
    ) {
        self.client = client
        self.config = AWSServiceConfig(
            region: region,
            partition: region?.partition ?? partition,
            serviceName: "SavingsPlans",
            serviceIdentifier: "savingsplans",
            serviceProtocol: .restjson,
            apiVersion: "2019-06-28",
            endpoint: endpoint,
            serviceEndpoints: Self.serviceEndpoints,
            errorType: SavingsPlansErrorType.self,
            middleware: middleware,
            timeout: timeout,
            byteBufferAllocator: byteBufferAllocator,
            options: options
        )
    }


    /// custom endpoints for regions
    static var serviceEndpoints: [String: String] {[
        "aws-global": "savingsplans.amazonaws.com",
        "aws-iso-e-global": "savingsplans.cloud.adc-e.uk",
        "aws-iso-f-global": "savingsplans.csp.hci.ic.gov",
        "cn-north-1": "savingsplans.cn-north-1.amazonaws.com.cn",
        "cn-northwest-1": "savingsplans.cn-northwest-1.amazonaws.com.cn"
    ]}



    // MARK: API Calls

    /// Creates a Savings Plan.
    @Sendable
    @inlinable
    public func createSavingsPlan(_ input: CreateSavingsPlanRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> CreateSavingsPlanResponse {
        try await self.client.execute(
            operation: "CreateSavingsPlan", 
            path: "/CreateSavingsPlan", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Creates a Savings Plan.
    ///
    /// Parameters:
    ///   - clientToken: A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
    ///   - commitment: The hourly commitment, in the same currency of the savingsPlanOfferingId. This is a value between 0.001 and 1 million. You cannot specify more than five digits after the decimal point.
    ///   - purchaseTime: The purchase time of the Savings Plan in UTC format (YYYY-MM-DDTHH:MM:SSZ).
    ///   - savingsPlanOfferingId: The ID of the offering.
    ///   - tags: One or more tags.
    ///   - upfrontPaymentAmount: The up-front payment amount. This is a whole number between 50 and 99 percent of the total value of the Savings Plan. This parameter is only supported if the payment option is Partial Upfront.
    ///   - logger: Logger use during operation
    @inlinable
    public func createSavingsPlan(
        clientToken: String? = CreateSavingsPlanRequest.idempotencyToken(),
        commitment: String,
        purchaseTime: Date? = nil,
        savingsPlanOfferingId: String,
        tags: [String: String]? = nil,
        upfrontPaymentAmount: String? = nil,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> CreateSavingsPlanResponse {
        let input = CreateSavingsPlanRequest(
            clientToken: clientToken, 
            commitment: commitment, 
            purchaseTime: purchaseTime, 
            savingsPlanOfferingId: savingsPlanOfferingId, 
            tags: tags, 
            upfrontPaymentAmount: upfrontPaymentAmount
        )
        return try await self.createSavingsPlan(input, logger: logger)
    }

    /// Deletes the queued purchase for the specified Savings Plan.
    @Sendable
    @inlinable
    public func deleteQueuedSavingsPlan(_ input: DeleteQueuedSavingsPlanRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> DeleteQueuedSavingsPlanResponse {
        try await self.client.execute(
            operation: "DeleteQueuedSavingsPlan", 
            path: "/DeleteQueuedSavingsPlan", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Deletes the queued purchase for the specified Savings Plan.
    ///
    /// Parameters:
    ///   - savingsPlanId: The ID of the Savings Plan.
    ///   - logger: Logger use during operation
    @inlinable
    public func deleteQueuedSavingsPlan(
        savingsPlanId: String,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> DeleteQueuedSavingsPlanResponse {
        let input = DeleteQueuedSavingsPlanRequest(
            savingsPlanId: savingsPlanId
        )
        return try await self.deleteQueuedSavingsPlan(input, logger: logger)
    }

    /// Describes the rates for the specified Savings Plan.
    @Sendable
    @inlinable
    public func describeSavingsPlanRates(_ input: DescribeSavingsPlanRatesRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> DescribeSavingsPlanRatesResponse {
        try await self.client.execute(
            operation: "DescribeSavingsPlanRates", 
            path: "/DescribeSavingsPlanRates", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Describes the rates for the specified Savings Plan.
    ///
    /// Parameters:
    ///   - filters: The filters.
    ///   - maxResults: The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
    ///   - nextToken: The token for the next page of results.
    ///   - savingsPlanId: The ID of the Savings Plan.
    ///   - logger: Logger use during operation
    @inlinable
    public func describeSavingsPlanRates(
        filters: [SavingsPlanRateFilter]? = nil,
        maxResults: Int? = nil,
        nextToken: String? = nil,
        savingsPlanId: String,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> DescribeSavingsPlanRatesResponse {
        let input = DescribeSavingsPlanRatesRequest(
            filters: filters, 
            maxResults: maxResults, 
            nextToken: nextToken, 
            savingsPlanId: savingsPlanId
        )
        return try await self.describeSavingsPlanRates(input, logger: logger)
    }

    /// Describes the specified Savings Plans.
    @Sendable
    @inlinable
    public func describeSavingsPlans(_ input: DescribeSavingsPlansRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> DescribeSavingsPlansResponse {
        try await self.client.execute(
            operation: "DescribeSavingsPlans", 
            path: "/DescribeSavingsPlans", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Describes the specified Savings Plans.
    ///
    /// Parameters:
    ///   - filters: The filters.
    ///   - maxResults: The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
    ///   - nextToken: The token for the next page of results.
    ///   - savingsPlanArns: The Amazon Resource Names (ARN) of the Savings Plans.
    ///   - savingsPlanIds: The IDs of the Savings Plans.
    ///   - states: The current states of the Savings Plans.
    ///   - logger: Logger use during operation
    @inlinable
    public func describeSavingsPlans(
        filters: [SavingsPlanFilter]? = nil,
        maxResults: Int? = nil,
        nextToken: String? = nil,
        savingsPlanArns: [String]? = nil,
        savingsPlanIds: [String]? = nil,
        states: [SavingsPlanState]? = nil,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> DescribeSavingsPlansResponse {
        let input = DescribeSavingsPlansRequest(
            filters: filters, 
            maxResults: maxResults, 
            nextToken: nextToken, 
            savingsPlanArns: savingsPlanArns, 
            savingsPlanIds: savingsPlanIds, 
            states: states
        )
        return try await self.describeSavingsPlans(input, logger: logger)
    }

    /// Describes the offering rates for the specified Savings Plans.
    @Sendable
    @inlinable
    public func describeSavingsPlansOfferingRates(_ input: DescribeSavingsPlansOfferingRatesRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> DescribeSavingsPlansOfferingRatesResponse {
        try await self.client.execute(
            operation: "DescribeSavingsPlansOfferingRates", 
            path: "/DescribeSavingsPlansOfferingRates", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Describes the offering rates for the specified Savings Plans.
    ///
    /// Parameters:
    ///   - filters: The filters.
    ///   - maxResults: The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
    ///   - nextToken: The token for the next page of results.
    ///   - operations: The specific Amazon Web Services operation for the line item in the billing report.
    ///   - products: The Amazon Web Services products.
    ///   - savingsPlanOfferingIds: The IDs of the offerings.
    ///   - savingsPlanPaymentOptions: The payment options.
    ///   - savingsPlanTypes: The plan types.
    ///   - serviceCodes: The services.
    ///   - usageTypes: The usage details of the line item in the billing report.
    ///   - logger: Logger use during operation
    @inlinable
    public func describeSavingsPlansOfferingRates(
        filters: [SavingsPlanOfferingRateFilterElement]? = nil,
        maxResults: Int? = nil,
        nextToken: String? = nil,
        operations: [String]? = nil,
        products: [SavingsPlanProductType]? = nil,
        savingsPlanOfferingIds: [String]? = nil,
        savingsPlanPaymentOptions: [SavingsPlanPaymentOption]? = nil,
        savingsPlanTypes: [SavingsPlanType]? = nil,
        serviceCodes: [SavingsPlanRateServiceCode]? = nil,
        usageTypes: [String]? = nil,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> DescribeSavingsPlansOfferingRatesResponse {
        let input = DescribeSavingsPlansOfferingRatesRequest(
            filters: filters, 
            maxResults: maxResults, 
            nextToken: nextToken, 
            operations: operations, 
            products: products, 
            savingsPlanOfferingIds: savingsPlanOfferingIds, 
            savingsPlanPaymentOptions: savingsPlanPaymentOptions, 
            savingsPlanTypes: savingsPlanTypes, 
            serviceCodes: serviceCodes, 
            usageTypes: usageTypes
        )
        return try await self.describeSavingsPlansOfferingRates(input, logger: logger)
    }

    /// Describes the offerings for the specified Savings Plans.
    @Sendable
    @inlinable
    public func describeSavingsPlansOfferings(_ input: DescribeSavingsPlansOfferingsRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> DescribeSavingsPlansOfferingsResponse {
        try await self.client.execute(
            operation: "DescribeSavingsPlansOfferings", 
            path: "/DescribeSavingsPlansOfferings", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Describes the offerings for the specified Savings Plans.
    ///
    /// Parameters:
    ///   - currencies: The currencies.
    ///   - descriptions: The descriptions.
    ///   - durations: The duration, in seconds.
    ///   - filters: The filters.
    ///   - maxResults: The maximum number of results to return with a single call. To retrieve additional results, make another call with the returned token value.
    ///   - nextToken: The token for the next page of results.
    ///   - offeringIds: The IDs of the offerings.
    ///   - operations: The specific Amazon Web Services operation for the line item in the billing report.
    ///   - paymentOptions: The payment options.
    ///   - planTypes: The plan types.
    ///   - productType: The product type.
    ///   - serviceCodes: The services.
    ///   - usageTypes: The usage details of the line item in the billing report.
    ///   - logger: Logger use during operation
    @inlinable
    public func describeSavingsPlansOfferings(
        currencies: [CurrencyCode]? = nil,
        descriptions: [String]? = nil,
        durations: [Int64]? = nil,
        filters: [SavingsPlanOfferingFilterElement]? = nil,
        maxResults: Int? = nil,
        nextToken: String? = nil,
        offeringIds: [String]? = nil,
        operations: [String]? = nil,
        paymentOptions: [SavingsPlanPaymentOption]? = nil,
        planTypes: [SavingsPlanType]? = nil,
        productType: SavingsPlanProductType? = nil,
        serviceCodes: [String]? = nil,
        usageTypes: [String]? = nil,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> DescribeSavingsPlansOfferingsResponse {
        let input = DescribeSavingsPlansOfferingsRequest(
            currencies: currencies, 
            descriptions: descriptions, 
            durations: durations, 
            filters: filters, 
            maxResults: maxResults, 
            nextToken: nextToken, 
            offeringIds: offeringIds, 
            operations: operations, 
            paymentOptions: paymentOptions, 
            planTypes: planTypes, 
            productType: productType, 
            serviceCodes: serviceCodes, 
            usageTypes: usageTypes
        )
        return try await self.describeSavingsPlansOfferings(input, logger: logger)
    }

    /// Lists the tags for the specified resource.
    @Sendable
    @inlinable
    public func listTagsForResource(_ input: ListTagsForResourceRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> ListTagsForResourceResponse {
        try await self.client.execute(
            operation: "ListTagsForResource", 
            path: "/ListTagsForResource", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Lists the tags for the specified resource.
    ///
    /// Parameters:
    ///   - resourceArn: The Amazon Resource Name (ARN) of the resource.
    ///   - logger: Logger use during operation
    @inlinable
    public func listTagsForResource(
        resourceArn: String,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> ListTagsForResourceResponse {
        let input = ListTagsForResourceRequest(
            resourceArn: resourceArn
        )
        return try await self.listTagsForResource(input, logger: logger)
    }

    /// Returns the specified Savings Plan.
    @Sendable
    @inlinable
    public func returnSavingsPlan(_ input: ReturnSavingsPlanRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> ReturnSavingsPlanResponse {
        try await self.client.execute(
            operation: "ReturnSavingsPlan", 
            path: "/ReturnSavingsPlan", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Returns the specified Savings Plan.
    ///
    /// Parameters:
    ///   - clientToken: A unique, case-sensitive identifier that you provide to ensure the idempotency of the request.
    ///   - savingsPlanId: The ID of the Savings Plan.
    ///   - logger: Logger use during operation
    @inlinable
    public func returnSavingsPlan(
        clientToken: String? = ReturnSavingsPlanRequest.idempotencyToken(),
        savingsPlanId: String,
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> ReturnSavingsPlanResponse {
        let input = ReturnSavingsPlanRequest(
            clientToken: clientToken, 
            savingsPlanId: savingsPlanId
        )
        return try await self.returnSavingsPlan(input, logger: logger)
    }

    /// Adds the specified tags to the specified resource.
    @Sendable
    @inlinable
    public func tagResource(_ input: TagResourceRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> TagResourceResponse {
        try await self.client.execute(
            operation: "TagResource", 
            path: "/TagResource", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Adds the specified tags to the specified resource.
    ///
    /// Parameters:
    ///   - resourceArn: The Amazon Resource Name (ARN) of the resource.
    ///   - tags: One or more tags. For example, { "tags": {"key1":"value1", "key2":"value2"} }.
    ///   - logger: Logger use during operation
    @inlinable
    public func tagResource(
        resourceArn: String,
        tags: [String: String],
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> TagResourceResponse {
        let input = TagResourceRequest(
            resourceArn: resourceArn, 
            tags: tags
        )
        return try await self.tagResource(input, logger: logger)
    }

    /// Removes the specified tags from the specified resource.
    @Sendable
    @inlinable
    public func untagResource(_ input: UntagResourceRequest, logger: Logger = AWSClient.loggingDisabled) async throws -> UntagResourceResponse {
        try await self.client.execute(
            operation: "UntagResource", 
            path: "/UntagResource", 
            httpMethod: .POST, 
            serviceConfig: self.config, 
            input: input, 
            logger: logger
        )
    }
    /// Removes the specified tags from the specified resource.
    ///
    /// Parameters:
    ///   - resourceArn: The Amazon Resource Name (ARN) of the resource.
    ///   - tagKeys: The tag keys.
    ///   - logger: Logger use during operation
    @inlinable
    public func untagResource(
        resourceArn: String,
        tagKeys: [String],
        logger: Logger = AWSClient.loggingDisabled        
    ) async throws -> UntagResourceResponse {
        let input = UntagResourceRequest(
            resourceArn: resourceArn, 
            tagKeys: tagKeys
        )
        return try await self.untagResource(input, logger: logger)
    }
}

extension SavingsPlans {
    /// Initializer required by `AWSService.with(middlewares:timeout:byteBufferAllocator:options)`. You are not able to use this initializer directly as there are not public
    /// initializers for `AWSServiceConfig.Patch`. Please use `AWSService.with(middlewares:timeout:byteBufferAllocator:options)` instead.
    public init(from: SavingsPlans, patch: AWSServiceConfig.Patch) {
        self.client = from.client
        self.config = from.config.with(patch: patch)
    }
}
